#include "vm.h"
#include "obj_thread.h"

/**
 * @brief 为运行函数准备栈帧
*/
void prepare_frame(ObjThread *obj_thread, ObjClosure *obj_closure, Value *stack_start)
{
    ASSERT(obj_thread->frame_capacity > obj_thread->used_frame_num, "frame not enough!!");

    Frame *frame = &(obj_thread->frames[obj_thread->used_frame_num ++]);

    // thread中的各个frame是共享thread的stack
    // frame用frame->stack_start指向各自frame在thread_stack中的起始地址
    frame->stack_start = stack_start;
    frame->closure = obj_closure;

    frame->ip = obj_closure->fn->instruct_stream.datas;
}

/**
 * @brief 新建线程
*/
ObjThread* new_objThread(VM *vm, ObjClosure *obj_closure)
{
    ASSERT(obj_closure != NULL, "objClosure is null!");

    Frame *frames = ALLOCATE_ARRAY(vm, Frame, INITIAL_FRAME_NUM);

    uint32_t stack_capacity = ceil_to_power_of_2(obj_closure->fn->max_stack_slot_used_num + 1);
    Value *new_stack = ALLOCATE_ARRAY(vm, Value, stack_capacity);

    ObjThread *obj_thread = ALLOCATE(vm, ObjThread);
    init_objheader(vm, &obj_thread->obj_header, OT_THREAD, vm->thread_class);

    obj_thread->frames = frames;
    obj_thread->frame_capacity = INITIAL_FRAME_NUM;
    obj_thread->stack = new_stack;
    obj_thread->stack_capacity = stack_capacity;

    reset_thread(obj_thread, obj_closure);
    return obj_thread;
}

/**
 * @brief 充值thread
*/
void reset_thread(ObjThread *obj_thread, ObjClosure *obj_closure)
{
    obj_thread->esp = obj_thread->stack;
    obj_thread->open_upvalues = NULL;
    obj_thread->caller = NULL;
    obj_thread->error_obj = VT_TO_VALUE(VT_NULL);
    obj_thread->used_frame_num = 0;

    ASSERT(obj_closure != NULL, "objClosure is NULL in function resetThread");
    prepare_frame(obj_thread, obj_closure, obj_thread->stack);
}